<?php defined('SYSPATH') or die('No direct script access.');

/**
 * Class Model_Image
 */
class Model_Image extends Model_Base
{
    protected $config;
    protected $imageDir;
    protected $thumbDir;
    protected $imageWidth;
    protected $imageHeight;
    protected $imageRandomStr;
    protected $thumbWidth;
    protected $thumbHeight;
    protected $urlPath;
    protected $urlPathThumb;
    protected $directory;
    protected $thumbDirFull;


    public function __construct()
    {
        $this->config         = Kohana::$config->load('base')->get('default');
        $this->imageDir       = $this->config['upload']['imageDir']; // Ordner in dem das Bild gespeichert wird
        $this->thumbDir       = $this->config['upload']['thumbDir'];

        $this->imageWidth     = $this->config['upload']['imageWidth'];
        $this->imageHeight    = $this->config['upload']['imageHeight'];
        $this->imageRandomStr = $this->config['upload']['imageRandomStr'];

        $this->thumbWidth     = $this->config['upload']['thumbWidth'];
        $this->thumbHeight    = $this->config['upload']['thumbHeight'];

        $this->urlPath        = $this->imageDir . date('Y') . '/' . date('m') . '/';
        $this->urlPathThumb   = $this->imageDir . date('Y') . '/' . date('m') . '/' . $this->thumbDir;
        $this->directory      = DOCROOT . $this->imageDir . date('Y') . '/' . date('m') . '/';
        $this->thumbDirFull   = DOCROOT . $this->imageDir . date('Y') . '/' . date('m') . '/' . $this->thumbDir;
    }


    /**
     * Holt alle Bilder aus der DB
     * @todo Funktion überarbeiten bzw entfernen
     *
     * @return object
     */
    public function getAllImages()
    {
        $query = DB::select('*')
                ->from($this->table);

        $result = $query->execute($this->_db);
        return $result;
    }

    /**
     * Holt Bilder Informationen
     *
     * @param string $imagePath
     * @return array/mixed
     */
    public function getImageInfos($imagePath)
    {
        $infos = exif_read_data($imagePath);
        $infos['FileSize'] = round($infos['FileSize'] / 1024, 2); // in KB
        return $infos;
    }

    /**
     * Zählt die Bilder eines Benutzers
     *
     * @param int $userId
     * @return object
     */
    public function countImagesFromUser($userId)
    {
        $result = DB::select(array(DB::expr('COUNT(`user`)'), 'total_images'))
                    ->from($this->table)
                    ->where('user', '=', $userId)
                    ->execute($this->_db);

        $count = $result->current();
        return $count['total_images'];
    }


    /**
     * Holt die Bilder eines Benutzers
     *
     * @param (int) $userId
     * @param (int) $offset
     * @param (int) $itemsPerPage
     * @return array
     */
    public function getAllImagesFromUser($userId, $offset, $itemsPerPage)
    {
        $result = DB::select()
                    ->from($this->table)
                    ->where('user', '=', $userId)
                    ->offset($offset)
                    ->limit($itemsPerPage)
                    ->order_by('id', 'desc')
                    ->execute($this->_db);
        $images = $result->as_array();
        return $this->betterPath($images);
    }

    /**
     * Zählt alle Bilder eines Users
     *
     * @param (int) $userId
     * @return int
     */
    public function countAllImagesFormUser($userId)
    {
        $result = DB::select()
            ->from($this->table)
            ->where('user', '=', $userId)
            ->execute($this->_db);
        $images = $result->as_array();
        return count($images);
    }

    /**
     * Wandelt den kompletten Path des Images in die Kurzform für URLs
     *
     * @param $images
     * @return array
     */
    protected function betterPath($images)
    {
        foreach ($images as $image) {
            $image['path'] = explode('/', $image['path']);

            krsort($image['path']);

            $image['path'] = array_filter($image['path']);
            $image['path'] = array_values($image['path']);

            for ($i = 0; $i < 3; $i++) {
                $path[] = $image['path'][$i];
            }

            krsort($path);

            $image['path'] = implode("/", $path);
            $newImages[] = $image;
            unset($path);
        }
        return $newImages;
    }


    /**
     * Speichert ein Bild auf dem Server im image Ordner
     *
     * @param  array $image
     * @param  int $resizeWidth
     * @return array
     */
    public function saveImage(array $image, $resizeWidth)
    {
        if (
            ! Upload::valid($image) OR
            ! Upload::not_empty($image) OR
            ! Upload::type($image, array('jpg', 'jpeg', 'png', 'gif')) OR
            ! Upload::image($image))
        {
            return false;
        }

        if (
            ! is_dir($this->directory)
            OR ! is_writable(realpath($this->directory))
            OR ! is_dir($this->thumbDirFull)
            OR ! is_writable(realpath($this->thumbDirFull)))
        {
            try {
                $old = umask(0);
                // Create directory (3. Parameter für verschachtelte Verzeichnisse)
                mkdir($this->thumbDirFull, 0777, true);
                umask($old);
            } catch (Kohana_Exception $e) {
                echo 'Could not create directory!: ',  $e->getMessage(), "\n";
            }
        }

        if ($file = Upload::save($image, NULL, $this->directory)) {

            // solange Zufallsstring erzeugen bis ein nicht existierender Erzeugt ist
            do {
                $filename = strtolower(Text::random('alnum', $this->imageRandomStr)).'.jpg';
            } while (file_exists($this->directory . $filename) === true);

            $imageNew = new Image_GD($file);
            if ($imageNew->width > $this->imageWidth) {
                if (isset($resizeWidth) && $resizeWidth < $this->imageWidth) {
                    $this->imageWidth = $resizeWidth;
                    $this->imageHeight = NULL;
                    $imageNew->resize($this->imageWidth, $this->imageHeight);
                } else {
                    $imageNew->resize($this->imageWidth, $this->imageHeight, Image::NONE);
                }
                $imageNew->save($this->directory.$filename);
            } else {
                if (isset($resizeWidth) && $resizeWidth < $this->imageWidth) {
                    $imageNew->resize($this->resizeWidth, NULL);
                } else {
                    // do nothing
                }
                $imageNew->save($this->directory.$filename);
            }

            if ($this->_saveThumb($file, $filename, $this->thumbDirFull, $this->thumbWidth, $this->thumbHeight)) {
                $result['thumb'] = $this->urlPathThumb . $filename;
            }
            $result['image'] = $this->urlPath . $filename;

            unlink($file);
        }

        /**
         * Bildinfos in DB speichern
         */
        $user = Auth::instance()->get_user();
        if ($user) {
            $data = array(
                'name' => $image['name'],
                'newName' => $filename,
                'uploadDate' => Date::formatted_time('now'),
                'size' => $image['size'],
                'path' => $this->directory,
                'pathThumb' => $this->thumbDirFull,
                'user' => $user->id,
            );
            $insert = $this->create($data);
            if ($result['thumb'] && $result['image'] && $insert) {
                return $result;
            }
        } else {
            if ($result['thumb'] && $result['image']) {
                return $result;
            }
        }

        return false;
    }

    /**
     * Generiert und Speichert Bild Thumbnail
     *
     * @param array $file
     * @param string $filename
     * @param string $thumbDir
     * @param int $thumbWidth
     * @param int $thumbHeight
     * @return bool
     */
    protected function _saveThumb($file, $filename, $thumbDir, $thumbWidth, $thumbHeight = NULL)
    {
        $thumb = new Image_GD($file);

        if ($thumb->width > 120) {
            $thumb->resize($thumbWidth, $thumbHeight);
            return $thumb->save($thumbDir.$filename);
        } else {
            return $thumb->save($thumbDir.$filename);
        }
    }


    /**
     * Holt Remote Bild und speichert dieses auf dem Server
     *
     * @param string $remoteImgPath
     * @param int $resizeWidth
     * @return array
     */
    public function saveRemoteImage($remoteImgPath, $resizeWidth)
    {
        if (
            ! is_dir($this->directory)
            OR ! is_writable(realpath($this->directory))
            OR ! is_dir($this->thumbDirFull)
            OR ! is_writable(realpath($this->thumbDirFull)))
        {
            try {
                $old = umask(0);
                // Create directory (3. Parameter für verschachtelte Verzeichnisse)
                mkdir($this->thumbDirFull, 0777, true);
                umask($old);
            } catch (Kohana_Exception $e) {
                echo 'Could not create directory!: ',  $e->getMessage(), "\n";
            }
        }

        // solange Zufallsstring erzeugen bis ein nicht existierender Erzeugt ist
        do {
            $filename = strtolower(Text::random('alnum', $this->imageRandomStr)).'.jpg';
        } while (file_exists($this->directory . $filename) === true);

        // Infos des Remote Bildes holen
        $imageInfos = exif_read_data($remoteImgPath);


        $image = Curl::get($remoteImgPath);
        if ($image) {
            $savefile = fopen($this->directory . $filename, 'w');
            fwrite($savefile, $image);
            fclose($savefile);
        } else {
            return false;
        }

        $isImage = getimagesize($this->directory . $filename);
        if (isset($isImage['mime'])) {
            $imageNew = new Image_GD($this->directory . $filename);
            if ($imageNew->width > $this->imageWidth) {
                if (isset($resizeWidth) && $resizeWidth < $this->imageWidth) {
                    $this->imageWidth = $resizeWidth;
                    $this->imageHeight = NULL;
                    $imageNew->resize($this->imageWidth, $this->imageHeight);
                } else {
                    $imageNew->resize($this->imageWidth, $this->imageHeight, Image::NONE);
                }
                $imageNew->save($this->directory.$filename);
            } else {
                if (isset($resizeWidth) && $resizeWidth < $this->imageWidth) {
                    $imageNew->resize($this->resizeWidth, NULL);
                } else {
                    // do nothing
                }
                $imageNew->save($this->directory.$filename);
            }

            if ($this->_saveThumb($this->directory . $filename, $filename, $this->thumbDirFull, $this->thumbWidth, $this->thumbHeight)) {
                $result['thumb'] = $this->urlPathThumb . $filename;
            }
            $result['image'] = $this->urlPath . $filename;

            /**
             * Bildinfos in DB speichern
             */
            $user = Auth::instance()->get_user();
            if ($user) {
                $data = array(
                    'name' => $imageInfos['FileName'],
                    'newName' => $filename,
                    'uploadDate' => Date::formatted_time('now'),
                    'size' => $imageInfos['FileSize'],
                    'path' => $this->directory,
                    'pathThumb' => $this->thumbDirFull,
                    'user' => $user->id,
                );
                $insert = $this->create($data);
                if ($result['thumb'] && $result['image'] && $insert) {
                    return $result;
                }
            } else {
                if ($result['thumb'] && $result['image']) {
                    return $result;
                }
            }

        } else {
            unlink($this->directory . $filename); // Löschen wenn kein Bild
            return false;
        }

    }


    /**
     * Verarbeitet die Bilder des Multi Uploads
     *
     * @param array $images
     * @param $resizeWidth
     * @return array
     */
    public function saveMultiImage(array $images, $resizeWidth)
    {
        $files = array();
        $fdata = $images;

        if (is_array($fdata['name'])){
            foreach ($fdata['name'] as $i => $d) {
                $files[] = array(
                    'name'     => $d,
                    'type'     => $fdata['type'][$i],
                    'tmp_name' => $fdata['tmp_name'][$i],
                    'error'    => $fdata['error'][$i],
                    'size'     => $fdata['size'][$i]
                );
            }
        }
        else {
            $files[] = $fdata;
        }

        foreach ($files as $file) {
            $resultSave[] = $this->saveImage($file, $resizeWidth);
        }

        return $resultSave;
    }

}